import os
import operator
import csv
import json
from geopy.distance import geodesic
from gps2grid import SpatialRegion

def grid_statistic():
    SR = SpatialRegion(41.4459657, 11.7531545505395, 42.302192553508, 12.9634722613942,300,300,1)
    row_num = SR.num_y
    col_num = SR.num_x
    print("row_num:",row_num,'col_num:',col_num)
    blk_info = {}
    with open("./place/1min.csv", "r") as f:
        reader = csv.reader(f)
        for gps in reader:
            lat = float(gps[0])
            lon = float(gps[1])
            blk = SR.coord2cell(lat, lon)
            
            if not blk_info.__contains__(blk):
                blk_info[blk] = []
            blk_info[blk].append((lat, lon))
            
    json_data = json.dumps(blk_info, indent = 4)
    
    with open('./place/1min_300.json', 'w') as f2:
        f2.write(json_data)


def get_valid_blk(i):
    col_num = 338
    blk = [i, i+1, i-1, i+col_num, i+col_num+1,i+col_num-1,i-col_num,i-col_num+1,i-col_num-1]
    for b in blk:
        if b < 1 or b > 107484:
            blk.remove(b)
    return blk


def mean_val(clust):
    sum_lat = 0
    sum_lon = 0
    for item in clust:
        sum_lat += item[0]
        sum_lon += item[1]
    return (sum_lat/len(clust), sum_lon/len(clust))


def KMeans(radius):
    SR = SpatialRegion(41.4459657, 11.7531545505395, 42.302192553508, 12.9634722613942,300,300,1)
    gps = []
    with open("./place/1min.csv", "r") as f:
        reader = csv.reader(f)
        for item in reader:
            gps.append((float(item[0]), float(item[1])))
            
    gps = set(gps)

    with open('./place/1min_300.json') as bf:
        blk_gps = json.load(bf)
        for key in blk_gps.keys():
            for i in range(len(blk_gps[key])):
                blk_gps[key][i] = tuple(blk_gps[key][i])

    place = []
    flag = True
    while gps:
        if flag is True:
            mean = gps.pop()
        clust = [mean]
        
        blks = get_valid_blk(SR.coord2cell(mean[0], mean[1]))
        for blk in blks:
            bi = str(blk)
            if not blk_gps.__contains__(bi):
                continue
            else:
                for point in blk_gps[bi]:
                    dist = geodesic(mean, point).meters
                    if dist <= radius:
                        clust.append(point)

        new_mean = mean_val(clust)
        if geodesic(mean,new_mean).meters < 1:
            clust = set(clust)
            flag = True
            place.append(new_mean)
            gps = gps-clust
            for blk in blks:
                bi = str(blk)
                if not blk_gps.__contains__(bi):
                    continue
                blk_gps[bi] = list(set(blk_gps[bi]) - clust)

            print('len_place:', len(place), 'len_gps:',len(gps))
        else:
            mean = new_mean
            flag = False

    with open('./place/1min_'+str(radius)+'m.csv', 'w', newline='') as csvfile:
        spamwriter = csv.writer(csvfile)
        spamwriter.writerows(place)


if __name__ == '__main__':
    #grid_statistic()
    KMeans(300)
    # grid_statistic()